using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;

namespace SharpMud.MudLib.Common.Resourcing
{
    /// <summary>
    /// A nice class that implementers of IGuidIdentifiedResourceHost or IUriIdentifiedResourceHost
    /// may use to track resources
    /// </summary>
    public class PrivateResourcingHelper : IGuidIdentifiedResourceHost, IUriIdentifiedResourceHost
    {
        #region Private Variables
        private Uri _BaseUri;
        private List<IHasInstanceGuid> _GuidIdentifiedResources;
        private List<IHasInstanceUri> _UriIdentifiedResources;
        private List<IGuidIdentifiedResourceHost> _GuidProxies;
        private List<IUriIdentifiedResourceHost> _UriProxies;
        #endregion

        #region Constructors
        public PrivateResourcingHelper()
            :this(null)
        {
        }
        public PrivateResourcingHelper(System.Uri baseUri)
        {
            _GuidIdentifiedResources = new List<IHasInstanceGuid>();
            _UriIdentifiedResources = new List<IHasInstanceUri>();
            _BaseUri = baseUri;
        }
        #endregion

        #region Public Methods
        public IHasInstanceGuid[] GetGuidResourcesHere()
        {
            return _GuidIdentifiedResources.ToArray();
        }

        public IHasInstanceUri[] GetUriResourcesHere()
        {
            return _UriIdentifiedResources.ToArray();
        }
        public IUriIdentifiedResourceHost[] GetUriProxiesHere()
        {
            return _UriProxies.ToArray();
        }
        public IGuidIdentifiedResourceHost[] GetGuidProxiesHere()
        {
            return _GuidProxies.ToArray();
        }

        public void AddResource(IHasInstanceGuid resource)
        {
            if (!_GuidIdentifiedResources.Contains(resource))
            {
                _GuidIdentifiedResources.Add(resource);
            }
        }

        public void AddResource(IHasInstanceUri resource)
        {
            if (!_UriIdentifiedResources.Contains(resource))
            {
                if (_BaseUri == null)
                    throw new InvalidOperationException();
                if (!_BaseUri.IsBaseOf(resource.ID))
                    throw new ArgumentException();
                _UriIdentifiedResources.Add(resource);
            }
        }

        public void AddResourceProxy(IGuidIdentifiedResourceHost resourceProxy)
        {
            if (!_GuidProxies.Contains(resourceProxy))
                _GuidProxies.Add(resourceProxy);
        }

        public void AddResourceProxy(IUriIdentifiedResourceHost resourceProxy)
        {
            if (!_UriProxies.Contains(resourceProxy))
            {
                if (_BaseUri == null)
                    throw new InvalidOperationException();
                if (!_BaseUri.IsBaseOf(resourceProxy.BaseUri))
                    throw new ArgumentException();
                _UriProxies.Add(resourceProxy);
            }
        }

        public void RemoveResource(IHasInstanceGuid resource)
        {
            if (_GuidIdentifiedResources.Contains(resource))
            {
                _GuidIdentifiedResources.Remove(resource);
            }
        }

        public void RemoveResource(IHasInstanceUri resource)
        {
            _UriIdentifiedResources.Remove(resource);
        }

        public void RemoveResourceProxy(IGuidIdentifiedResourceHost resourceProxy)
        {
            if (_GuidProxies.Contains(resourceProxy))
                _GuidProxies.Remove(resourceProxy);
        }

        public void RemoveResourceProxy(IUriIdentifiedResourceHost resourceProxy)
        {
            if (_UriProxies.Contains(resourceProxy))
            {
                _UriProxies.Remove(resourceProxy);
            }
        }
        #endregion

        #region IGuidIdentifiedResourceHost Members

        public bool IsDefined(Guid guid)
        {
            foreach (IHasInstanceGuid hig in this._GuidIdentifiedResources)
            {
                if (hig.ID == guid)
                    return true;
            }
            foreach (IGuidIdentifiedResourceHost girh in this._GuidProxies)
            {
                if (girh.IsDefined(guid))
                    return true;
            }
            return false;
        }

        public object GetResource(Guid guid)
        {
            foreach (IHasInstanceGuid hig in this._GuidIdentifiedResources)
            {
                if (hig.ID == guid)
                    return hig;
            }
            foreach (IGuidIdentifiedResourceHost girh in this._GuidProxies)
            {
                if (girh.IsDefined(guid))
                {
                    return girh.GetResource(guid);
                }
            }
            return null;
        }

        #endregion


        #region IUriIdentifiedResourceHost Members

        public Uri BaseUri
        {
            get { return _BaseUri; }
        }

        public bool IsDefined(Uri resourceIndicator)
        {
            if (!_BaseUri.IsBaseOf(resourceIndicator))
                return false;

            foreach (IHasInstanceUri hiu in this._UriIdentifiedResources)
            {
                if (hiu.ID.Equals(resourceIndicator))
                    return true;
            }
            foreach (IUriIdentifiedResourceHost uirh in this._UriProxies)
            {
                if (uirh.IsDefined(resourceIndicator))
                    return true;
            }
            return false;
        }

        public object GetResource(Uri resourceIndicator)
        {
            if (!_BaseUri.IsBaseOf(resourceIndicator))
                return false;

            foreach (IHasInstanceUri hiu in this._UriIdentifiedResources)
            {
                if (hiu.ID.Equals(resourceIndicator))
                    return hiu;
            }
            foreach (IUriIdentifiedResourceHost uirh in this._UriProxies)
            {
                if (uirh.IsDefined(resourceIndicator))
                {
                    return uirh.GetResource(resourceIndicator);
                }
            }
            return null;
        }
        #endregion
    }
}
